package edu.cmu.ibill.model;

import java.util.ArrayList;
import java.util.Collections;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import edu.cmu.ibill.databeans.*;

/**
 * 
 * @author Yunkai Zhang
 * 
 */
public class CategoryDictDAO {

	private BeanFactory<CategoryDict> factory;

	private String[] categories = { "auto", "bills & utilities",
			"business services", "education", "entertainment",
			"fees & charges", "financial & invest", "food & dining",
			"gifts & charities", "health care", "home", "income", "loan",
			"kids", "others", "payment", "personal care", "pets", "shopping",
			"taxes", "transfer", "travel/vacation" };

	/**
	 * Constructor
	 * 
	 * @param driver
	 * @param URL
	 * @param user
	 * @param pw
	 * @throws DAOException
	 */
	public CategoryDictDAO(String driver, String URL, String user, String pw)
			throws DAOException {
		try {
			// Get a BeanTable to create the "photo" table

			BeanTable.useJDBC(driver, URL, user, pw);

			BeanTable<CategoryDict> categoryDictTable = BeanTable.getInstance(
					CategoryDict.class, "ibill_categorydict");

			if (!categoryDictTable.exists()) {
				categoryDictTable.create("id");
				factory = categoryDictTable.getFactory();
				InsertData();
			}

			if (factory == null)
				factory = categoryDictTable.getFactory();

			categoryDictTable.setIdleConnectionCleanup(true);

			// Get a BeanFactory which the actions will use to read and write
			// rows of the "likeable" table
		} catch (BeanFactoryException e) {
			throw new DAOException(e);
		}
	}

	/**
	 * Insert all the categories into the CategoryDict table.
	 * 
	 * @throws DAOException
	 */
	private void InsertData() throws DAOException {
		for (int i = 0; i < categories.length; i++) {
			String category = categories[i];
			CategoryDict cd = new CategoryDict(category);
			create(cd);
		}

	}

	/**
	 * Given a certain category name, return the corresponding CategoryDict
	 * object.
	 * 
	 * @param id
	 * @return
	 */
	public CategoryDict Lookup(int id) {
		CategoryDict category = null;

		try {
			CategoryDict[] list = factory.match(MatchArg.equals("id", id));
			if (list.length > 0)
				category = list[0];
		} catch (RollbackException e) {
			return null;
		}

		return category;
	}

	/**
	 * Given a certain category id, return the corresponding name of a category.
	 * 
	 * @param id
	 * @return
	 */
	public String LookupCategoryName(int id) {
		String category = null;

		if (id == 0)
			return null;

		try {
			CategoryDict[] list = factory.match(MatchArg.equals("id", id));
			if (list.length > 0) {
				category = list[0].getCategoryName();
			}
		} catch (RollbackException e) {
			return null;
		}

		return category;
	}

	public int getCategoryID(String categoryName) {
		int id = -1;

		try {
			CategoryDict[] list = factory.match(MatchArg.equals("categoryName",
					categoryName));
			if (list != null && list.length > 0)
				id = list[0].getId();
		} catch (RollbackException e) {
			return -1;
		}

		return id;
	}

	/**
	 * Return an ArrayList which contains the category names, which are in the
	 * increasing order of the category id. The first object's id is 0 and the
	 * name of this category is an empty string.
	 * 
	 * @return
	 */
	public CategoryDict[] getAllCategoryNames() {
		ArrayList<CategoryDict> categoryList = new ArrayList<CategoryDict>();

		CategoryDict zero = new CategoryDict();
		zero.setId(0);
		zero.setCategoryName("");

		try {
			CategoryDict[] list = factory.match();
			categoryList.add(zero);
			for (CategoryDict cd : list)
				categoryList.add(cd);
		} catch (RollbackException e) {
			return null;
		}

		Collections.sort(categoryList);

		return (CategoryDict[]) categoryList
				.toArray(new CategoryDict[categoryList.size()]);
	}

	/**
	 * Insert a categoryDict into the table.
	 * 
	 * @param cd
	 * @throws DAOException
	 */
	private void create(CategoryDict cd) throws DAOException {
		try {
			Transaction.begin();

			CategoryDict dbCategoryDict = factory.create();
			factory.copyInto(cd, dbCategoryDict);

			Transaction.commit();
		} catch (RollbackException e) {
			throw new DAOException(e);
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}
}
